package com.zhongkun.datahome.service.service.impl;

import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.zhongkun.datahome.common.constant.CacheConstants;
import com.zhongkun.datahome.common.core.redis.RedisCache;
import com.zhongkun.datahome.common.exception.ServiceException;
import com.zhongkun.datahome.common.utils.SecurityUtils;
import com.zhongkun.datahome.core.service.ISysConfigService;
import com.zhongkun.datahome.service.domain.MiniProgramConfig;
import com.zhongkun.datahome.service.service.IFileService;
import com.zhongkun.datahome.service.service.IWeixinService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author huangjie
 * @since 2025/5/6
 */
@Slf4j
@Service
public class WeixinServiceImpl implements IWeixinService {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IFileService fileService;

    @Autowired
    private ISysConfigService sysConfigService;

    /**
     * 微信小程序登录获取openid和session_key
     *
     * @param appid
     * @param loginCode
     * @return
     */
    @Override
    public String getPhoneNumber(String appid, String loginCode) {
        String accessToken = getAccessToken(appid);
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + accessToken;
        Map<String, String> params = new HashMap<>();
        params.put("code", loginCode); // 前端传来的code

        // 使用RestTemplate发送请求
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, String>> request = new HttpEntity<>(params, headers);
        ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);
        log.info("response.getBody() = {}", JSON.toJSONString(response.getBody()));
        // 解析结果
        JSONObject phoneInfo = Objects.requireNonNull(response.getBody()).getJSONObject("phone_info");
        return phoneInfo.getString("purePhoneNumber");
    }

    @Override
    public String getCustomerMiniProgram(Long customerHouseId) {
        MiniProgramConfig config = getConfig(SecurityUtils.getTenantId());
        if (config == null) {
            throw new ServiceException("未配置小程序信息");
        }
        String accessToken = getAccessToken(config.getAppid());

        String apiUrl = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken;
        Map<String, Object> param = new HashMap<>();
        param.put("page", "pages/userhome/index");  // 页面路径（需在小程序注册）
        param.put("scene", "houseId=" + customerHouseId);
        // 发送请求并获取二进制数据
        byte[] qrCodeBytes = HttpRequest.post(apiUrl)
                .header(Header.CONTENT_TYPE, "application/json")  // 必须指定 JSON 格式
                .body(JSONObject.toJSONString(param))
                .execute()
                .bodyBytes();

        return fileService.uploadData(qrCodeBytes);
    }

    private String getAccessToken(String appid) {
        // 从缓存中获取access_token
        String redisKey = CacheConstants.WX_ACCESS_TOKEN + appid;
        String accessToken = redisCache.getCacheObject(redisKey);
        if (accessToken != null) {
            return accessToken;
        }
        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/stable_token";
        Map<String, Object> params = new HashMap<>();
        params.put("grant_type", "client_credential");
        params.put("appid", appid);
        params.put("secret", getAppSecret(appid));
        JSONObject tokenResponse = JSON.parseObject(HttpUtil.post(tokenUrl, JSON.toJSONString(params)));

        accessToken = tokenResponse.getString("access_token");
        redisCache.setCacheObject(redisKey, accessToken, 7000, TimeUnit.SECONDS);
        return accessToken;
    }

    private String getAppSecret(String appid) {
        String config = sysConfigService.selectConfigByKey("sys.mini.program.config");
        List<MiniProgramConfig> miniProgramConfigList = JSONArray.parseArray(config, MiniProgramConfig.class);
        for (MiniProgramConfig miniProgramConfig : miniProgramConfigList) {
            if (miniProgramConfig.getAppid().equals(appid)) {
                return miniProgramConfig.getSecret();
            }
        }
        return "";
    }

    private MiniProgramConfig getConfig(Long tenantId) {
        String config = sysConfigService.selectConfigByKey("sys.mini.program.config");
        List<MiniProgramConfig> miniProgramConfigList = JSONArray.parseArray(config, MiniProgramConfig.class);
        for (MiniProgramConfig miniProgramConfig : miniProgramConfigList) {
            if (miniProgramConfig.getTenantId().equals(tenantId)) {
                return miniProgramConfig;
            }
        }
        return null;
    }

}
